#include "XInputMgr.h"

#define CHECK_INDEX(iIndex) if (iIndex < 0 || iIndex >= MAX_CONTROLLERS){return 0;}if (!m_akControllers[iIndex].bConnected){return 0;} 

CXInputMgr::CXInputMgr(void)
{
	m_bDeadZoneOn = true;
	m_hWnd = NULL;
	m_dwMsg = 0;
}

CXInputMgr::~CXInputMgr(void)
{
}

void CXInputMgr::Init( HWND hWnd,DWORD dwMsg )
{
	m_hWnd = hWnd;
	m_dwMsg= dwMsg;
}

void CXInputMgr::EnableXInput()
{
	XInputEnable(TRUE);
}

void CXInputMgr::DisableXInput()
{
	XInputEnable(FALSE);
}

void CXInputMgr::Update()
{
	if (m_hWnd != GetActiveWindow())
	{
		for (int i = 0;i < MAX_CONTROLLERS;i++)
		{
			SetLeftVibration(i,0,0);
			SetRightVibration(i,0,0);

			m_akControllers[i].Clear();
		}

		DisableXInput();				
	}
	else
	{
		EnableXInput();

		DWORD dwResult = 0; 
		XINPUT_CAPABILITIES kCap;

		for (DWORD i = 0;i < MAX_CONTROLLERS;i++)
		{	
			m_akControllers[i].Clear();

			XInputGetState(i,&m_akControllers[i].kState);
			m_akControllers[i].bConnected = false;

			dwResult = XInputGetCapabilities(i,XINPUT_FLAG_GAMEPAD,&kCap);
			if (dwResult != ERROR_SUCCESS)
			{
				continue;
			}

			if (kCap.SubType != XINPUT_DEVSUBTYPE_GAMEPAD)
			{
				continue;
			}

			m_akControllers[i].bConnected = true;

			if( m_bDeadZoneOn )
			{
				// Zero value if thumbsticks are within the dead zone 
				if( (m_akControllers[i].kState.Gamepad.sThumbLX < INPUT_DEADZONE && m_akControllers[i].kState.Gamepad.sThumbLX > -INPUT_DEADZONE) && 
					(m_akControllers[i].kState.Gamepad.sThumbLY < INPUT_DEADZONE && m_akControllers[i].kState.Gamepad.sThumbLY > -INPUT_DEADZONE) ) 
				{   
					m_akControllers[i].kState.Gamepad.sThumbLX = 0;
					m_akControllers[i].kState.Gamepad.sThumbLY = 0;
				}

				if( (m_akControllers[i].kState.Gamepad.sThumbRX < INPUT_DEADZONE && m_akControllers[i].kState.Gamepad.sThumbRX > -INPUT_DEADZONE) && 
					(m_akControllers[i].kState.Gamepad.sThumbRY < INPUT_DEADZONE && m_akControllers[i].kState.Gamepad.sThumbRY > -INPUT_DEADZONE) ) 
				{
					m_akControllers[i].kState.Gamepad.sThumbRX = 0;
					m_akControllers[i].kState.Gamepad.sThumbRY = 0;
				}
			}		
		}	

		DWORD dwRet = 0;
		XINPUT_KEYSTROKE kStroke;
		
		for (int i = 0;i < MAX_CONTROLLERS;i++)
		{			
			ZeroMemory(&kStroke,sizeof(kStroke));
			dwRet = XInputGetKeystroke(i,XINPUT_FLAG_GAMEPAD,&kStroke);
			if (dwRet == ERROR_SUCCESS)
			{
				if (kStroke.Flags & XINPUT_KEYSTROKE_KEYUP)
				{
					m_akKeyDownState[i][kStroke.VirtualKey] = false;				 
					PostMessage(m_hWnd,m_dwMsg,MAKEWPARAM(XInput_Up,i),MAKELPARAM(kStroke.VirtualKey,0));
				}
				else if (kStroke.Flags & XINPUT_KEYSTROKE_KEYDOWN)
				{
					bool bDown = m_akKeyDownState[i][kStroke.VirtualKey];
					PostMessage(m_hWnd,m_dwMsg,MAKEWPARAM(XInput_Down,i),MAKELPARAM(kStroke.VirtualKey,bDown));
					m_akKeyDownState[i][kStroke.VirtualKey] = true;
				}
			}			
		}

		for (int i = 0;i < MAX_CONTROLLERS;i++)
		{
			for (int j = 0;j < VIBRATOR_NUM;j++)
			{
				VibrationInfo& rkInfo = m_akVibrationInfo[i][j];
				if (rkInfo.iStartTime > 0)
				{
					if (GetTickCount() > (DWORD)rkInfo.iEndTime)
					{
						j == 0 ? SetLeftVibration(i,0,0) : SetRightVibration(i,0,0); 
					}
				}
			}
		}
	}
	
	return;
}

bool CXInputMgr::IsDPadUpPressed( int iIndex )
{
	CHECK_INDEX(iIndex);

	return m_akControllers[iIndex].kState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP;
}

bool CXInputMgr::IsDPadDownPressed( int iIndex )
{
	CHECK_INDEX(iIndex);

	return (m_akControllers[iIndex].kState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) > 0;
}

bool CXInputMgr::IsDPadLeftPressed( int iIndex )
{
	CHECK_INDEX(iIndex);

	return (m_akControllers[iIndex].kState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) > 0;
}

bool CXInputMgr::IsDPadRightPressed( int iIndex )
{
	CHECK_INDEX(iIndex);

	return (m_akControllers[iIndex].kState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) > 0;
}

bool CXInputMgr::IsButtonStartDown( int iIndex )
{
	CHECK_INDEX(iIndex);

	return (m_akControllers[iIndex].kState.Gamepad.wButtons & XINPUT_GAMEPAD_START) > 0;
}

bool CXInputMgr::IsButtonBackDown( int iIndex )
{
	CHECK_INDEX(iIndex);

	return (m_akControllers[iIndex].kState.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) > 0;
}

bool CXInputMgr::IsButtonLSDown( int iIndex )
{
	CHECK_INDEX(iIndex);

	return (m_akControllers[iIndex].kState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) > 0;
}

bool CXInputMgr::IsButtonRSDown( int iIndex )
{
	CHECK_INDEX(iIndex);

	return (m_akControllers[iIndex].kState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) > 0;
}

bool CXInputMgr::IsButtonLBDown( int iIndex )
{
	CHECK_INDEX(iIndex);

	return (m_akControllers[iIndex].kState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) > 0;
}

bool CXInputMgr::IsButtonRBDown( int iIndex )
{
	CHECK_INDEX(iIndex);

	return (m_akControllers[iIndex].kState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) > 0;
}

bool CXInputMgr::IsButtonADown( int iIndex )
{
	CHECK_INDEX(iIndex);

	return (m_akControllers[iIndex].kState.Gamepad.wButtons & XINPUT_GAMEPAD_A) > 0;
}

bool CXInputMgr::IsButtonBDown( int iIndex )
{
	CHECK_INDEX(iIndex);

	return (m_akControllers[iIndex].kState.Gamepad.wButtons & XINPUT_GAMEPAD_B) > 0;
}

bool CXInputMgr::IsButtonXDown( int iIndex )
{
	CHECK_INDEX(iIndex);

	return (m_akControllers[iIndex].kState.Gamepad.wButtons & XINPUT_GAMEPAD_X) > 0;
}

bool CXInputMgr::IsButtonYDown( int iIndex )
{
	CHECK_INDEX(iIndex);

	return (m_akControllers[iIndex].kState.Gamepad.wButtons & XINPUT_GAMEPAD_Y) > 0;
}

bool CXInputMgr::IsButtonLTDown( int iIndex )
{
	return GetButtonLTValue(iIndex) > 200;
}

bool CXInputMgr::IsButtonRTDown( int iIndex )
{
	return GetButtonRTValue(iIndex) > 200;
}

int CXInputMgr::GetButtonLTValue( int iIndex )
{
	CHECK_INDEX(iIndex);

	return m_akControllers[iIndex].kState.Gamepad.bLeftTrigger;
}

int CXInputMgr::GetButtonRTValue( int iIndex )
{
	CHECK_INDEX(iIndex);

	return m_akControllers[iIndex].kState.Gamepad.bRightTrigger;
}

CXInputMgr::StickXY CXInputMgr::GetLStickValue( int iIndex )
{
	if (iIndex >= 0 && iIndex < MAX_CONTROLLERS)
	{
		return StickXY(m_akControllers[iIndex].kState.Gamepad.sThumbLX,m_akControllers[iIndex].kState.Gamepad.sThumbLY);
	}

	return StickXY();
}

CXInputMgr::StickXY CXInputMgr::GetRStickValue( int iIndex )
{
	if (iIndex >= 0 && iIndex < MAX_CONTROLLERS)
	{
		return StickXY(m_akControllers[iIndex].kState.Gamepad.sThumbRX,m_akControllers[iIndex].kState.Gamepad.sThumbRY);
	}

	return StickXY();
}

void CXInputMgr::SetCheckDeadZone( bool bCheck )
{
	m_bDeadZoneOn = bCheck;
}

bool CXInputMgr::SetLeftVibration( int iIndex,int iValue,int iTime )
{
	CHECK_INDEX(iIndex);

	VibrationInfo& rkInfo = m_akVibrationInfo[iIndex][0];
	rkInfo.iIndex = iIndex;
	rkInfo.iValue = iValue;
	rkInfo.iStartTime = iValue <= 0 ? 0 : GetTickCount();
	rkInfo.iEndTime = iValue <= 0 ? 0 : GetTickCount() + iTime;

	XINPUT_VIBRATION kVibration;
	ZeroMemory(&kVibration,sizeof(XINPUT_VIBRATION));
	kVibration.wLeftMotorSpeed = iValue; // use any value between 0-65535 here
	kVibration.wRightMotorSpeed = m_akVibrationInfo[iIndex][1].iValue; // use any value between 0-65535 here
	XInputSetState(iIndex,&kVibration);
	
	return true;
}

bool CXInputMgr::SetRightVibration( int iIndex,int iValue,int iTime )
{
	CHECK_INDEX(iIndex);

	VibrationInfo& rkInfo = m_akVibrationInfo[iIndex][1];
	rkInfo.iIndex = iIndex;
	rkInfo.iValue = iValue;
	rkInfo.iStartTime = iValue <= 0 ? 0 : GetTickCount();
	rkInfo.iEndTime = iValue <= 0 ? 0 : GetTickCount() + iTime;

	XINPUT_VIBRATION kVibration;
	ZeroMemory(&kVibration,sizeof(XINPUT_VIBRATION));
	kVibration.wLeftMotorSpeed = m_akVibrationInfo[iIndex][0].iValue; // use any value between 0-65535 here
	kVibration.wRightMotorSpeed = iValue; // use any value between 0-65535 here
	XInputSetState(iIndex,&kVibration);

	return true;
}
